package com.zf.actuator.endpoint.metric;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 自定义新的指标，指标内容会出现在 metrics 端点的响应中
 */
@Configuration
public class MyCustomMetricConfig {

    public static final String MY_NUMBER_COUNTER_1 = "my.number.v1";
    public static final String MY_NUMBER_COUNTER_2 = "my.number.v2";
    public static final String MY_NUMBER_COUNTER_3 = "my.number.v3";
    public static final String MY_NUMBER_COUNTER_4 = "my.number.v4";


    /**
     * 方式 1：使用构造方式定义新的指标
     */
    @Component
    public static class MyCustomMetric {

        /**
         * 通过构造注入 MeterRegistry
         */
        public MyCustomMetric(MeterRegistry registry) {
            /**
             * 添加一个计数器指标 到 MeterRegistry中
             * 由 {@link MetricController#incr()} 方法修改值
             */
            registry.counter(MY_NUMBER_COUNTER_1);

            // 添加一个指标，每次获取提供的对象（参数2）的值，获取的方式是 参数3
            registry.gauge(MY_NUMBER_COUNTER_4, DataObj.MONEY, AtomicLong::get);

            // 可以添加多个各种类型的指标，counter,timer,gauge

        }
    }


    /**
     * 方式 2：使用 MeterBinder 匿名类 方式定义新的指标
     */
    @Bean
    public MeterBinder randNumberMethod2() {
        return (registry) -> {
            /**
             * 增加一个指标，每次获取 DataObj.AGE 对象的值
             * 由 {@link MetricController#incr()} 方法修改值
             */
            Gauge.builder(
                    MY_NUMBER_COUNTER_2, DataObj.AGE, AtomicInteger::get
            ).register(registry);
            // 可以添加多个各种类型的指标，counter,timer,gauge
        };
    }


    /**
     * 方式 2：使用实现 MeterBinder 接口方式定义新的指标
     */
    @Component
    public static class MyMetric3 implements MeterBinder {

        @Override
        public void bindTo(MeterRegistry registry) {
            /**
             * 增加一个指标，每次获取 DataObj.ADDER 对象的值
             * 由 {@link MetricController#incr()} 方法修改值
             */
            Gauge.builder(MY_NUMBER_COUNTER_3, DataObj.ADDER, AtomicLong::get)
                    .register(registry);

            // 可以添加多个各种类型的指标，counter,timer,gauge
        }
    }


    /**
     * 定义一个简单的数据对象
     */
    public static class DataObj {
        public static final AtomicLong ADDER = new AtomicLong(0);
        public static final AtomicInteger AGE = new AtomicInteger(12);
        public static final AtomicLong MONEY = new AtomicLong(90);
    }
}
